// PersistentCreate.cpp: implementation of the PersistentCreate class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "PersistentCreate.h"
#include "Volume.h"
#include "AssocCommon.h"
#include "Part.h"
#include "Supporthanger.h"
#include "Joint.h"
#include "Project.h"
#include "PartTypeVariable.h"
#include "ProjectManager.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
using namespace PropertySystem;

namespace PersistentObjectOperation
{
	PersistentCreate::PersistentCreate()
	{
		
	}
	
	PersistentCreate::~PersistentCreate()
	{
		
	}
	
	BOOL PersistentCreate::Visit(Volume*& pVolume)
	{
		ASSERT(pVolume);
		ASSERT(pVolume->IsCreateState());

		CString strSql;
		strSql.Format(_T("Insert Into [volume] (VolumeID, VolumeName, description) values ('%d' ,'%s','%s')"), 
			pVolume->VolumeID(), pVolume->Name(), pVolume->Description());
		
		BOOL bResult = PersistentExecute(strSql, pVolume->project());
		pVolume->SetRead();
		return bResult;
	}
	
	BOOL PersistentCreate::Visit(Part*& pPart)
	{
		ASSERT(pPart);
		ASSERT(pPart->IsCreateState());
		ASSERT(pPart->SupportHangerOwner());

		SupportHanger* pSH = pPart->SupportHangerOwner();

		AcGePoint3d OriginalPt;
		AcGeVector3d vX;
		AcGeVector3d vY;
		AcGeVector3d vZ;

		AcGeMatrix3d matrix = pPart->ModelMatrix();
		matrix.getCoordSystem(OriginalPt, vX, vY, vZ);

		CString strSql;
		strSql.Format(_T("Insert Into [Parts_Of_SupportHanger] (SH_ID, Part_ID, \
						PF_ID, Part_Standard_ID, Pos_X, Pos_Y, Pos_Z, Dir_X_X, Dir_X_Y, Dir_X_Z,\
						Dir_Z_X, Dir_Z_Y, Dir_Z_Z, Attach) values ('%s', %d, '%s', '%s',\
						%g, %g, %g,\
						%g, %g, %g,\
						%g, %g, %g, %s)"),
						pSH->SupportHangerID(), pPart->PartIndex(),
						pPart->GetCustomID(), pPart->GetStandard(),
						OriginalPt.x, OriginalPt.y, OriginalPt.z,
						vX.x, vX.y, vX.z,
						vZ.x, vZ.y, vZ.z,
						pPart->IsAttach()?_T("true"):_T("false"));

		BOOL bResult = PersistentExecute(strSql, pPart->project());
		ASSERT(bResult);
		if(!bResult)
			return bResult;
		bResult = PersistentPartPropertys(pPart);
		pPart->SetRead();

		return bResult;
	}
	
	BOOL PersistentCreate::Visit(SupportHanger*& pSH)
	{
		ASSERT(pSH);
		ASSERT(pSH->IsCreateState());
		ASSERT(pSH->SupportHangerEntry());

		CString strSql;
		strSql.Format(_T("Insert Into [supporthanger] (SH_ID, SH_Name, SH_VolumeID, SH_EntryPart_ID, IsCheckOut)\
			values ('%s', '%d', '%s', '%d', %s)"),
			pSH->SupportHangerID(), (INT)(pSH->Id()), pSH->GetSupportHangerPoint().VolumeID(),
			pSH->SupportHangerEntry()->PartIndex(), pSH->IsCheckOut()?_T("true"):_T("false"));

		BOOL bResult = PersistentExecute(strSql, pSH->project());
		pSH->SetRead();
		return bResult;
	}
	
	BOOL PersistentCreate::Visit(Joint*& pJoint)
	{
		ASSERT(pJoint);
		ASSERT(pJoint->IsCreateState());
		ASSERT(pJoint->SupportHangerOwner());

		CString strSql;
		strSql.Format(_T("Insert Into [Joints_Of_SupportHanger] (SH_ID, Joint_ID, Part_ID_1,\
			JP_ID_1, Part_ID_2, JP_ID_2) values ('%s', %d, '%d', '%s', '%d', '%s')"),
			pJoint->SupportHangerOwner()->SupportHangerID(),
			pJoint->JointIndex(),
			pJoint->PrevPartID(),
			pJoint->PrevPortID(),
			pJoint->NextPartID(),
			pJoint->NextPortID());

		BOOL bResult = PersistentExecute(strSql, pJoint->project());
		PersistentPartPropertys(pJoint);

		pJoint->SetRead();
		return bResult;
	}
	
	BOOL PersistentCreate::PersistentPartPropertys(SupportHangerSubObject* pPart)
	{
		BOOL bResult = TRUE;
		ASSERT(pPart);
		PropertyStack* pStack = pPart->GetPropertyStack();
		ASSERT(pStack);

		CString strSql;
		SupportHanger* pSH = pPart->SupportHangerOwner();
		ASSERT(pSH);

		ASSERT(!pSH->SupportHangerID().IsEmpty());
		ASSERT(!pSH->GetSupportHangerPoint().VolumeID().IsEmpty());

		PropertyStack::Iterator* pIterator = pStack->NewSavePropertyIterator();
		if(pIterator == NULL)
		{
			ASSERT(pIterator);
			::ReportMemoryError();
		}

		for(pIterator->Begin(); !pIterator->End(); pIterator->Next())
		{
			Variable* pVar = pIterator->Get();
			ASSERT(pVar);
			ASSERT(!pVar->GetSymbol().IsEmpty());
			ASSERT(!((CString)(*pVar)).IsEmpty());;
			
			strSql.Format(_T("Insert Into [Properties_Of_Part] (SH_ID, Part_ID, Property_ID, Property_Value) values\
							('%s',%d, '%s', '%s')"),pSH->SupportHangerID(),
							(INT)pPart->Id(), pVar->GetSymbol(), (CString)(*pVar));

			bResult = PersistentExecute(strSql, pPart->project());
			if(pVar->IsKindOf(UE_RUNTIME_CLASS(PropertySystem::PartTypeVariable)))
			{
				Part* pSubPart = (Part*)(*pVar);
				ASSERT(pSubPart->project());
				ASSERT(pSubPart->project()->versionController());
				pSubPart->Accept(&pSubPart->project()
					->versionController()->CurPersistentVisitor());				
			}
			ASSERT(bResult);

		}
		delete pIterator;
		return bResult;
	}

	BOOL PersistentCreate::PersistentSHParts(SupportHanger* pSH)
	{
		ASSERT(pSH);
		BOOL bResult = TRUE;

		PartManager& manager = pSH->GetPartManager();
		PartManager::Iterator* pIterator = manager.NewIterator();
		if(pIterator == NULL)
		{
			ASSERT(pIterator);
			::ReportMemoryError();
		}

		for(pIterator->Begin(); !pIterator->End(); pIterator->Next())
		{
			Part* pPart = pIterator->Get();
			ASSERT(pPart);
			bResult = pPart->Accept(this);
			ASSERT(bResult);
		}
		delete pIterator;
		return bResult;
	}

	BOOL PersistentCreate::PersistentJointAttachs(Joint* pJoint)
	{
		ASSERT(pJoint);

		BOOL bResult = TRUE;
		Joint::Iterator* pIterator = pJoint->NewAttachIterator();
		if(pIterator == NULL)
		{
			ASSERT(pIterator);
			::ReportMemoryError();
		}

		for(pIterator->Begin(); !pIterator->End(); pIterator->Next())
		{
			Part* pPart = pIterator->Get();
			ASSERT(pPart);

			CString strSql;
			strSql.Format(_T("Insert Into [Accessories_Of_JointPort] (Joint_ID, Accessory_ID)\
							values (%d, '%d')"),
			pJoint->JointIndex(),
			pPart->PartIndex());

			bResult = this->PersistentExecute(strSql, pJoint->project());
			ASSERT(bResult);
			
			ASSERT(pPart->project());
			ASSERT(pPart->project()->versionController());
			pPart->Accept(&pPart->project()
			->versionController()->CurPersistentVisitor());
			
		}
		delete pIterator;

		return bResult;
	}
	
	
	///////////////////////////////////////////////////////////
	
	PersistentCreateBatch::PersistentCreateBatch()
	{
	}
	
	PersistentCreateBatch::~PersistentCreateBatch()
	{
	}
	
	void PersistentCreateBatch::EndPersistent()
	{
		SaveVolume();

		if(!m_bHasModelElement)
			return;

		InitPropertyPtr();
		SaveSH();
		SavePart();
		SaveJoint();


		m_PropertyPtr->UpdateBatch(adAffectAll);
		m_PropertyPtr->Close();		
	}
	
	void PersistentCreateBatch::InitPropertyPtr()
	{
		if(!m_bHasModelElement)
			return;

		if(m_PropertyPtr == NULL || m_PropertyPtr->GetState() == adStateClosed)
		{
			try
			{
				CString strSql;
				strSql.Format(_T("Select * from Properties_Of_Part"));
				
				Project* pPrj = GetProjectManager().CurProject();
				ASSERT(pPrj);
				
				if(m_PropertyPtr == NULL)
					m_PropertyPtr.CreateInstance(__uuidof(Recordset));
				
				m_PropertyPtr->Open(_variant_t(strSql),(IDispatch*)pPrj->PrjSourcePtr(),
					adOpenDynamic,adLockOptimistic,adCmdText);
			}
			CATCH_COM_ERROR(m_PropertyPtr, NORETURN);
		}		
	}

	void PersistentCreateBatch::SaveVolume()
	{
		if(m_theVolumes.GetSize() == 0)
			return;
		
		CString strSql;
		strSql.Format(_T("select * from Volume"));
		
		Project* pPrj = GetProjectManager().CurProject();
		ASSERT(pPrj);
		_RecordsetPtr ptr;
		
		try
		{
			ptr.CreateInstance(__uuidof(Recordset));
			
			ptr->Open(_variant_t(strSql),(IDispatch*)pPrj->PrjSourcePtr(),
				adOpenDynamic,adLockOptimistic,adCmdText);

			for(int i = 0; i < m_theVolumes.GetSize(); i++)
			{
				Volume* pVolume =m_theVolumes.GetAt(i);
				ptr->AddNew();
				ptr->PutCollect(_T("VolumeID"), _variant_t((long)pVolume->VolumeID()));
				ptr->PutCollect(_T("VolumeName"), _variant_t(pVolume->Name()));
				ptr->PutCollect(_T("Description"), _variant_t(pVolume->Description()));

				pVolume->SetRead();
			}

			ptr->UpdateBatch(adAffectAll);
			ptr->Close();
		}
		CATCH_COM_ERROR(ptr, NORETURN);
	}
	
	void PersistentCreateBatch::SaveSH()
	{
		if(m_theSHs.GetSize() == 0)
			return;

		CString strSql;
		strSql.Format(_T("select * from SupportHanger"));
		
		Project* pPrj = GetProjectManager().CurProject();
		ASSERT(pPrj);
		_RecordsetPtr ptr;
		
		try
		{
			ptr.CreateInstance(__uuidof(Recordset));
			
			ptr->Open(_variant_t(strSql),(IDispatch*)pPrj->PrjSourcePtr(),
				adOpenDynamic,adLockOptimistic,adCmdText);
			

			for(int i = 0; i < m_theSHs.GetSize(); i++)
			{
				SupportHanger* pSH = m_theSHs.GetAt(i);
				ASSERT(pSH);
				ptr->AddNew();
				ptr->PutCollect(_T("SH_ID"), _variant_t(pSH->SupportHangerID()));
				ptr->PutCollect(_T("SH_Name"), _variant_t((long)((INT)pSH->Id())));
				ptr->PutCollect(_T("SH_VolumeID"), _variant_t(pSH->GetSupportHangerPoint().VolumeID()));
				ptr->PutCollect(_T("SH_EntryPart_ID"), _variant_t((long)(pSH->SupportHangerEntry()->PartIndex())));
				ptr->PutCollect(_T("IsCheckOut"), _variant_t(pSH->IsCheckOut()?true:false));

				ptr->UpdateBatch(adAffectAll);
				SaveProperty(pSH->GetPropertyStack(), pSH->SupportHangerID(), pSH->Id());
				
				pSH->SetRead();
			}

			ptr->Close();
		}
		CATCH_COM_ERROR(ptr, NORETURN);
	}
	
	void PersistentCreateBatch::SaveJoint()
	{
		if(m_theJoints.GetSize() == 0)
			return;

		CString strSql;
		strSql.Format(_T("select * from Joints_Of_SupportHanger"));
		
		Project* pPrj = GetProjectManager().CurProject();
		ASSERT(pPrj);
		_RecordsetPtr ptr;
		
		try
		{
			ptr.CreateInstance(__uuidof(Recordset));
			
			ptr->Open(_variant_t(strSql),(IDispatch*)pPrj->PrjSourcePtr(),
				adOpenDynamic,adLockOptimistic,adCmdText);

			for(int i = 0; i < m_theJoints.GetSize(); i++)
			{
				Joint* pJoint = m_theJoints.GetAt(i);
				ASSERT(pJoint);

				ptr->AddNew();
				ptr->PutCollect(_T("SH_ID"), _variant_t(pJoint->SupportHangerOwner()->SupportHangerID()));
				ptr->PutCollect(_T("Joint_ID"), _variant_t((long)pJoint->JointIndex()));
				ptr->PutCollect(_T("Part_ID_1"), _variant_t((long)pJoint->PrevPartID()));
				ptr->PutCollect(_T("JP_ID_1"), _variant_t(pJoint->PrevPortID()));
				ptr->PutCollect(_T("Part_ID_2"), _variant_t((long)pJoint->NextPartID()));
				ptr->PutCollect(_T("JP_ID_2"), _variant_t(pJoint->NextPortID()));

				SaveProperty(pJoint->GetPropertyStack(), 
					pJoint->SupportHangerOwner()->SupportHangerID(), pJoint->Id());

				pJoint->SetRead();
			}

			ptr->UpdateBatch(adAffectAll);
			ptr->Close();
		}
		CATCH_COM_ERROR(ptr, NORETURN);
	}
	
	void PersistentCreateBatch::SavePart()
	{
		if(m_theParts.GetSize() == 0)
			return;

		CString strSql;
		strSql.Format(_T("select * from [Parts_Of_SupportHanger]"));
		
		Project* pPrj = GetProjectManager().CurProject();
		ASSERT(pPrj);
		_RecordsetPtr ptr;
		
		try
		{
			ptr.CreateInstance(__uuidof(Recordset));
			
			ptr->Open(_variant_t(strSql),(IDispatch*)pPrj->PrjSourcePtr(),
				adOpenDynamic,adLockOptimistic,adCmdText);

			for(int i = 0; i < m_theParts.GetSize(); i++)
			{
				Part* pPart = m_theParts.GetAt(i);
				ASSERT(pPart);
				
				AcGePoint3d OriginalPt;
				AcGeVector3d vX;
				AcGeVector3d vY;
				AcGeVector3d vZ;
				
				AcGeMatrix3d matrix = pPart->ModelMatrix();
				matrix.getCoordSystem(OriginalPt, vX, vY, vZ);
				
				ptr->AddNew();
				ptr->PutCollect(_T("SH_ID"), _variant_t(pPart->SupportHangerOwner()->SupportHangerID()));
				ptr->PutCollect(_T("Part_ID"), _variant_t((long)pPart->PartIndex()));
				ptr->PutCollect(_T("PF_ID"), _variant_t(pPart->GetCustomID()));
				ptr->PutCollect(_T("Part_Standard_ID"), _variant_t(pPart->GetStandard()));
				ptr->PutCollect(_T("Pos_X"), _variant_t(OriginalPt.x));
				ptr->PutCollect(_T("Pos_Y"), _variant_t(OriginalPt.y));
				ptr->PutCollect(_T("Pos_Z"), _variant_t(OriginalPt.z));
				ptr->PutCollect(_T("Dir_X_X"), _variant_t(vX.x));
				ptr->PutCollect(_T("Dir_X_Y"), _variant_t(vX.y));
				ptr->PutCollect(_T("Dir_X_Z"), _variant_t(vX.z));
				ptr->PutCollect(_T("Dir_Z_X"), _variant_t(vZ.x));
				ptr->PutCollect(_T("Dir_Z_Y"), _variant_t(vZ.y));
				ptr->PutCollect(_T("Dir_Z_Z"), _variant_t(vZ.z));
				ptr->PutCollect(_T("Attach"), _variant_t(pPart->IsAttach()?true:false));

				SaveProperty(pPart->GetPropertyStack(), 
					pPart->SupportHangerOwner()->SupportHangerID(), pPart->Id());

				pPart->SetRead();
			}

			ptr->UpdateBatch(adAffectAll);
			ptr->Close();
		}
		CATCH_COM_ERROR(ptr, NORETURN);
	}
	
	void PersistentCreateBatch::SaveProperty(PropertyStack* pStack, const CString& strSHID, const UeObjectId& id)
	{
		ASSERT(pStack);

		PropertyStack::Iterator* pIterator = pStack->NewSavePropertyIterator();
		if(pIterator == NULL)
		{
			ASSERT(pIterator);
			::ReportMemoryError();
		}

		for(pIterator->Begin(); !pIterator->End(); pIterator->Next())
		{
			Variable* pVar = pIterator->Get();
			ASSERT(pVar);
			ASSERT(!pVar->GetSymbol().IsEmpty());
			ASSERT(!((CString)(*pVar)).IsEmpty());;
			
			try
			{
				m_PropertyPtr->AddNew();
				m_PropertyPtr->PutCollect(_T("SH_ID"), _variant_t(strSHID));
				m_PropertyPtr->PutCollect(_T("Part_ID"), _variant_t((long)(INT)id));
				m_PropertyPtr->PutCollect(_T("Property_ID"), _variant_t(pVar->GetSymbol()));
				m_PropertyPtr->PutCollect(_T("Property_Value"), _variant_t((CString)(*pVar)));
			}
			CATCH_COM_ERROR(m_PropertyPtr, NORETURN);
		}
		delete pIterator;
	}
}
